/*
 * Created on Dec 21, 2004
 */
package org.vectrics.recruiter.user.resume.email;

import java.io.InputStream;
import java.util.Date;

import javax.mail.Flags;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.Multipart;
import javax.mail.Part;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMultipart;

import org.apache.log4j.Logger;
import org.vectrics.SystemException;
import org.vectrics.batch.Batch;
import org.vectrics.common.util.DateSync;
import org.vectrics.config.MailConfiguration;
import org.vectrics.config.MailConfigurationImpl;
import org.vectrics.domain.Domain;
import org.vectrics.hibernate.ThreadProperties;
import org.vectrics.provider.CoreServiceLocator;
import org.vectrics.recruiter.RecruitServiceLocator;
import org.vectrics.recruiter.config.RecruitConfig;
import org.vectrics.recruiter.document.CandidateDocument;
import org.vectrics.recruiter.document.CandidateDocumentCategory;

/**
 * @author MMoore
 */
public class EmailedResumesBatchRunnable extends Batch implements Runnable {
	private transient Logger log = Logger.getLogger(this.getClass());
	static boolean running = false;
	
	public EmailedResumesBatchRunnable(Domain domain, MailConfiguration mailConfig) {
		super(domain);
	}

	public boolean hasOtherRunningInstance() {
		return(running);
	}
	
	protected String getDescription() {
		return("Scan e-mailed resumes");
	}

	protected String getBatchTypeCode() {
		return("emailed-resumes");
	}

	protected boolean persistRunResults() {
		return(true);
	}
	
	protected boolean logOnlyErrors() {
		return(true);
	}
	
	protected boolean executeForEachDomain() {
		return(true);
	}
	
	public void execute(Domain domain) {
		try {
			log.debug("Process emailed resumes for data owner: " + domain.getDescription());
			processEmailedResumesForDomain(domain);
		} catch (Exception ex) {
			log.error("Exception processing resumes for domain " + domain.getDescription(), ex);
		}
	}

	private void processEmailedResumesForDomain(Domain domain) {
		if (running)
			return;
		
		MailConfigurationImpl resumeRecipMailConfig = new MailConfigurationImpl(domain);
		resumeRecipMailConfig.setMailHost(RecruitConfig.getRecruitInstance().getResumeRecipientEmailHost(domain));
		resumeRecipMailConfig.setMailPassword(RecruitConfig.getRecruitInstance().getResumeRecipientEmailPassword(domain));
		resumeRecipMailConfig.setMailUserName(RecruitConfig.getRecruitInstance().getResumeRecipientEmailAddress(domain));
		if ((resumeRecipMailConfig.getMailHost() == null) || (resumeRecipMailConfig.getMailHost().trim().length() == 0)) {
			log.info("Domain doesn't have a host setup for receiving resume emails: " + domain.getDescription());
		} else {
			running = true;
			log.debug("Running batch job: Emailed resumes batch");
			Store store = null;
			Folder folder = null;
			try {
	
				log.debug("Open the Inbox folder");
				
				boolean allMessagesProcessed = false;
				while (allMessagesProcessed == false) {
					try {
						Session session = resumeRecipMailConfig.getMailSession();
						
						log.debug("Get the email store");
						String resumeEmailInboxType = RecruitConfig.getRecruitInstance().getEmailedResumeStoreType(domain);
						store = session.getStore(resumeEmailInboxType);
						store.connect(resumeRecipMailConfig.getMailHost(), resumeRecipMailConfig.getMailUserName(), 
								resumeRecipMailConfig.getMailPassword());
						folder = store.getFolder("INBOX");
						folder.open(Folder.READ_WRITE);
						Message messages[] = folder.getMessages();
						log.debug("Found inbox messages Resume Email box" +
								"\r\n - Domain: " + domain.getDescription()
								+ "\r\n - Email Box: " + resumeRecipMailConfig.getMailUserName()
								+ "\r\n - Message Count: " + messages.length
								);
					//	for (int i = 0, n=messages.length; i<n; i++) {
					   if (messages.length > 0) {
						   Message message = messages[0];
						   try {
							   storeResumeMessage(message, domain);
							   message.setFlag(Flags.Flag.DELETED, true);
						   } catch (Exception ex) {
							   log.error("Exception storing email message", ex);
						   }
						   
						 
					   } else {
						   allMessagesProcessed = true;
					   }
					} catch (Exception ex) {
						log.error("Exception retrieving emailed resumes", ex);
						throw new SystemException("Exception retrieving emailed resumes", ex);
					} finally {
						if (folder != null) {
							folder.close(true);
							try {
								store.close();
							} catch (Exception ex) {
								log.error("Exception closing email store", ex);
							}
						} else {
							log.warn("Attempt to close mail box folder, but folder does not exist");
						}
					}
				}
			} catch (Exception ex) {
				
				log.error("Exception processing resume e-mails, domain = " + domain.getDescription()
						+ "\r\n - Email user: " + resumeRecipMailConfig.getMailUserName() 
						+ "\r\n - Email host: " + resumeRecipMailConfig.getMailHost() 
						+ "\r\n - Email pwd: " + resumeRecipMailConfig.getMailPassword() 
						, ex);
				throw new SystemException("Exception processing resume e-mails", ex);
			} finally {
				// Close connection - flagged msgs will be deleted. 
				
			}
		}
		running = false;
		log.debug("Finished Running batch job: Emailed resumes batch");
	}

	
	private void storeResumeMessage(Message message, Domain domain) {
		try {
			log.info("Found emailed resume - storing message into FlashRecruit database, " +
				"\r\n - subject = " + message.getSubject()
				);
		} catch (Exception ex) {
			throw new SystemException("Exception displaying message info");
		}
		
		if (domain == null) {
			log.error("Data owner is null, needs to be assigned");
			throw new SystemException("Data owner is null");
		}
		
        String attachmentFileDirectory = RecruitConfig.getRecruitInstance().getEmailedResumeAttachmentFileDirectory(domain);
        log.debug("Attachment directory: " + attachmentFileDirectory);
		try {
			Date receivedDate = message.getReceivedDate();
			Date sentDate = message.getSentDate();
			String contentType = message.getContentType();
			String subject = message.getSubject();
			InternetAddress fromAddress = (InternetAddress)message.getFrom()[0];
			String fromEmailAddress = fromAddress.getAddress();
			String fromName = fromAddress.getPersonal();
			
			if (fromName == null)
				fromName = fromAddress.getAddress();
			if (log.isDebugEnabled()) {
				log.debug(
						"Message received in emailed resume inbox "
						+ "\r - Domain = " + domain.toString() 
						+ "\r - Received date = " + receivedDate 
						+ "\r - Subject = " + subject 
						+ "\r - Content Type = " + contentType
						+ "\r - From = " + fromEmailAddress
						+ "\r - From Personal = " + fromAddress.getPersonal()
						+ "\r - From type: " + fromAddress.getType()
						+ "\r - Class of message: " + message.getClass().getName());
			}
			/*
			if (message instanceof MimeMessage) {
				MimeMessage mimeMessage = (MimeMessage)message;
				String contentMD5 = mimeMessage.getContentMD5();
				log.debug("contentMD5 = " + contentMD5);
			}
			*/
			
			EmailedResumeInfo emailResumeInfo = new EmailedResumeInfo();
			emailResumeInfo.setDateSent(sentDate);
			emailResumeInfo.setDomain(domain);
			emailResumeInfo.setFromEmailAddress(fromEmailAddress);
			emailResumeInfo.setFromEmailName(fromName);
			if (subject == null)
				subject = "";
			emailResumeInfo.setEmailSubject(subject);
			
			RecruitServiceLocator.getRecruitUserService().updateEmailedResume(emailResumeInfo);
			log.debug("Saved emailed resume info, id = " + emailResumeInfo.getId());
			
			
			String emailBody = null;
			
			log.info("Content Type = " + message.getContentType());
			Object messageContent = message.getContent();
			if (messageContent != null) {
				if (messageContent instanceof MimeMultipart) {
					Multipart multiPart = (Multipart)messageContent;
					int partsCount = multiPart.getCount();
					for (int i = 0; i < partsCount; i++) {
						Part part = multiPart.getBodyPart(i);				
						String disposition = part.getDisposition();
						if (disposition == null) {
							  if (part.getContent() instanceof String) {
						    	  String body = (String)part.getContent();
						    	  CandidateDocument document = new CandidateDocument();
						    	  document.setDomain(domain);
						    	  document.setOriginalFileName(null);
							      if (partsCount == 1) {
							    	  log.debug("One attachment, assume body of email is cvr letter");
							    	  document.setCategory(CandidateDocumentCategory.CATEGORY_COVER_LETTER);
							      } else {
							    	  document.setCategory(CandidateDocumentCategory.CATEGORY_UNKNOWN);
							      }
							      document.setName("Email Body");
							      document.setDescription("Email received from: " + emailResumeInfo.getFromEmailAddress()
							    		  + "  Email Subject: " + emailResumeInfo.getEmailSubject());
							      RecruitServiceLocator.getRecruitUserService().createCandidateDocumentForUserTextEntered(document, body);
						    	  
						    	  
							      EmailedResumeAttachment attachment = emailResumeInfo.addAttachment();
							      attachment.setDateSaved(DateSync.getCurrentTime());
							      attachment.setDocument(document);
							      attachment.setDomain(domain);
							      Long fileNameIndex = CoreServiceLocator.getSurrogateKeyService().getKey(RecruitConfig.SURROGATE_KEY_EMAIL_RESUME_ATTCH_FILE);
							      RecruitServiceLocator.getRecruitUserService().updateEmailedResumeAttachment(attachment);
							  } else {
								  log.warn("Do no know how to handle email part content with class: "
										  + part.getContent().getClass().getName());  
							  }
						} else if (disposition.equals(Part.ATTACHMENT)) {
						//    saveFile(part.getFileName(), part.getInputStream());
						      String partFileName = part.getFileName();
						      log.debug("Attachment: " + partFileName);
						      
					    	  CandidateDocument document = new CandidateDocument();
					    	  document.setDomain(domain);
					    	  document.setOriginalFileName(partFileName);
						      if (partsCount == 1) {
						    	  log.debug("One attachment, assume attachment is resume");
						  		  document.setCategory(CandidateDocumentCategory.CATEGORY_RESUME);
						      } else {
						  		  document.setCategory(CandidateDocumentCategory.CATEGORY_UNKNOWN);
						      }
						      document.setName("Email Attachment");
						      document.setDescription("Email attachment received from: " + emailResumeInfo.getFromEmailAddress()
						    		  + "  Email Subject: " + emailResumeInfo.getEmailSubject()
						    	);
					    	  
						      InputStream attachmentData = part.getDataHandler().getInputStream();
						      RecruitServiceLocator.getRecruitUserService().createCandidateDocument(document, partFileName, attachmentData);
						      
						      
						      EmailedResumeAttachment attachment = emailResumeInfo.addAttachment();
						      attachment.setDomain(domain);
						      attachment.setDateSaved(DateSync.getCurrentTime());
						      attachment.setDocument(document);
						      RecruitServiceLocator.getRecruitUserService().updateEmailedResumeAttachment(attachment);
					     } else if (disposition.equals(Part.INLINE)) {
					     } else {
					    	 throw new SystemException("Do not know how to handle " +
					    	 		"disposition = " + disposition);
					     }
					}
					RecruitServiceLocator.getRecruitUserService().updateEmailedResume(emailResumeInfo);
				} else if (message.getContent() instanceof String) {
					log.debug("Content class = " + message.getContent().getClass().getName());
					emailBody = (String)message.getContent();
				} else {
					throw new SystemException("Do not know how to handle message content class: "
							+ message.getContent().getClass().getName());
				}
			} else {
				log.warn("Message content was null");
			}
			
			if (emailBody != null) {
			  log.debug("Write email body to a file and make it just another attachment");
 			  String body = null;
		    	CandidateDocument document = new CandidateDocument();
				try {
					body = emailBody;
			    	document.setDomain(domain);
			    	document.setOriginalFileName(null);
				    document.setName("Email Body");
				    document.setDescription("Email received from: " + emailResumeInfo.getFromEmailAddress()
				    		  + "  Email Subject: " + emailResumeInfo.getEmailSubject());
				    document.setCategory(CandidateDocument.UNKNOWN_TYPE);
			    	  
				    RecruitServiceLocator.getRecruitUserService().createCandidateDocumentForUserTextEntered(document, body);
			    	  
				    EmailedResumeAttachment attachment = emailResumeInfo.addAttachment();
				    attachment.setDateSaved(DateSync.getCurrentTime());
				    attachment.setDocument(document);
				    attachment.setDomain(domain);

				    RecruitServiceLocator.getRecruitUserService().updateEmailedResume(emailResumeInfo);
				    ThreadProperties.forcedCommit();
				} catch (Exception ex) {
					log.error("Exception saving e-mail body as attachment" +
							"\r\n - Body =              " + body +
							"\r\n - Document.category = " + document.getCategory()
							, ex);
				}
			}
			
		 //RecruitUserProvider.getInstance().updateEmailedResume(emailResumeInfo);
         /*			
			while (headerEnum.hasMoreElements()) {
				Header header = (Header)headerEnum.nextElement();
				log.debug("Header: " + header.getName()  + "  Value: " + header.getValue());
			}
		 */
		} catch (Exception ex) {
			log.error("Exception processing message", ex);
		}
		
	}
	
/*  Snippet from attachment read example - JavaWorld article	
    // -- Get the message part (i.e. the message itself) --
    Part messagePart=message;
    Object content=messagePart.getContent();

    // -- or its first body part if it is a multipart message --
    if (content instanceof Multipart)
    {
      messagePart=((Multipart)content).getBodyPart(0);
      System.out.println("[ Multipart Message ]");
    }

    // -- Get the content type --
    String contentType=messagePart.getContentType();

    // -- If the content is plain text, we can print it --
    System.out.println("CONTENT:"+contentType);

    if (contentType.startsWith("text/plain")
     || contentType.startsWith("text/html"))
    {
      InputStream is = messagePart.getInputStream();

      BufferedReader reader
       =new BufferedReader(new InputStreamReader(is));
      String thisLine=reader.readLine();

      while (thisLine!=null)
      {
        System.out.println(thisLine);
        thisLine=reader.readLine();
      }
    }

    System.out.println("-----------------------------");
*/	
}
